﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Sakura.Media.AviSynth
{
	/// <summary>
	/// 表示一个片段。无法继承该类型。
	/// </summary>
	public sealed class AvsClip : ICloneable, IDisposable
	{
		/// <summary>
		/// 对象的内部指针。
		/// </summary>
		internal IntPtr ptr;

		/// <summary>
		/// 构造一个新的片段。
		/// </summary>
		/// <param name="ptr">新片段的内部指针。</param>
		private AvsClip(IntPtr ptr)
		{
			this.ptr = ptr;
		}

		/// <summary>
		/// 创建一个 <see cref="AvsClip"/> 对象。如果指针无效，则返回 <c>null</c>。
		/// </summary>
		/// <param name="ptr">要创建的剪辑对象的内部指针。</param>
		/// <returns>包装后的剪辑对象；如果指针无效，则返回 <c>null</c>。</returns>
		internal static AvsClip Create(IntPtr ptr)
		{
			if (ptr != IntPtr.Zero)
			{
				return new AvsClip(ptr);
			}
			else
			{
				return null;
			}
		}


		#region 方法封装

		/// <summary>
		/// 创建一个当前剪辑对象的副本。
		/// </summary>
		/// <returns>当前对象的副本。如果无法有效复制对象，则返回 <c>null</c>。</returns>
		/// <exception cref="System.ObjectDisposedException">当前对象已经被释放。</exception>
		public AvsClip Clone()
		{
			this.CheckDisposed();

			var ptr = Native.NativeMethods.avs_copy_clip(this.ptr);
			return Create(ptr);
		}

		/// <summary>
		/// 创建一个当前剪辑对象的副本。
		/// </summary>
		/// <returns>当前对象的副本。如果无法有效复制对象，则返回 <c>null</c>。</returns>
		/// <exception cref="System.ObjectDisposedException">当前对象已经被释放。</exception>
		object ICloneable.Clone()
		{
			return this.Clone();
		}

		/// <summary>
		/// 获取当前剪辑的版本。
		/// </summary>
		public int Version
		{
			get
			{
				this.CheckDisposed();

				return Native.NativeMethods.avs_get_version(this.ptr);
			}
		}

		#endregion

		#region 资源管理

		/// <summary>
		/// 获取一个值，指示当前对象是否已经被释放。
		/// </summary>
		public bool IsDisposed
		{
			get
			{
				return this.ptr == IntPtr.Zero;
			}
		}

		/// <summary>
		/// 确保对象没有被释放。
		/// </summary>
		public void CheckDisposed()
		{
			if (this.IsDisposed)
			{
				throw new ObjectDisposedException(null);
			}
		}


		#region IDisposable 成员

		/// <summary>
		/// 释放该对象占用的所有资源。
		/// </summary>
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// 释放该对象占用的所有资源。
		/// </summary>
		/// <param name="disposing">指定是否需要释放非托管资源。</param>
		private void Dispose(bool disposing)
		{
			if (disposing)
			{
				// 如果已经释放，则不进行任何操作。
				if (!this.IsDisposed)
				{
					// 使用内部锁防止多线程占用问题。
					var p = Interlocked.Exchange(ref this.ptr, IntPtr.Zero);

					// 释放指针。
					Native.NativeMethods.avs_release_clip(p);
				}
			}
		}

		/// <summary>
		/// 析构方法。
		/// </summary>
		~AvsClip()
		{
			this.Dispose(false);
		}

		#endregion
		#endregion
	}
}
